package com.robaone.api.business;

import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.FileItem;
import org.json.JSONObject;

import com.robaone.api.data.AppDatabase;
import com.robaone.api.data.SessionData;

public class ActionDispatcher {
	private SessionData session;
	private HttpServletRequest request;
	private HttpServletResponse response;
	public static final String ACTION_PACKAGE_NAME = "com.robaone.api.action_package";
	private String ACTION_PACKAGE = System.getProperty(ACTION_PACKAGE_NAME);
	public ActionDispatcher(SessionData session,HttpServletRequest request,HttpServletResponse response){
		this.session = session;
		this.request = request;
		this.setResponse(response);
	}
	public void setPackage(String action_package){
		ACTION_PACKAGE = action_package;
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void runAction(String action,Map parameters,OutputStream out) throws Exception {
		try{
			if(action == null || action.trim().length() == 0){
				throw new Exception("No action specified");
			}
			AppDatabase.writeLog("00007: Running Action, "+action);
			String data = parameters.get("data") == null ? "{}" : ((String[])parameters.get("data"))[0];
			if(data.length() == 0) data = "{}";
			AppDatabase.writeLog("00008: Data = "+data);
			Class[] parameterTypes = new Class[]{JSONObject.class};
			Class myClass = Class.forName(ACTION_PACKAGE+"."+action.split("[.]")[0]);
			Method meth = myClass.getMethod(action.split("[.]")[1], parameterTypes);
			Class[] constrpartypes = new Class[]{OutputStream.class,SessionData.class,HttpServletRequest.class};
			Constructor constr = myClass.getConstructor(constrpartypes);
			Object o = constr.newInstance(new Object[]{out,session,request});
			JSONObject jo = new JSONObject(data);
			Object[] arglist = new Object[]{jo};
			meth.invoke(o, arglist);
			if(o instanceof BaseAction){
				BaseAction base = (BaseAction)o;
				//this.response.setContentType(base.getContentType());
				if(base.getSQLStream() != null){
					base.getSQLStream().CopyStream(out);
				}else{
					base.writeResonse();
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public String runFormAction(Map parameterMap,
			OutputStream out) throws Exception {
		try{
			String action = this.getParameter(parameterMap,"_action");
			AppDatabase.writeLog("00009: Running Action, "+action);
			JSONObject data = new JSONObject(parameterMap);
			AppDatabase.writeLog("00010: Data = "+data.toString());
			Class[] parameterTypes = new Class[]{JSONObject.class};
			Class myClass = Class.forName(ACTION_PACKAGE+"."+action.split("[.]")[0]);
			Method meth = myClass.getMethod(action.split("[.]")[1], parameterTypes);
			Class[] constrpartypes = new Class[]{OutputStream.class,SessionData.class,HttpServletRequest.class};
			Constructor constr = myClass.getConstructor(constrpartypes);
			Object o = constr.newInstance(new Object[]{out,session,request});
			Object[] arglist = new Object[]{data};
			meth.invoke(o, arglist);
			if(o instanceof BaseAction){
				((BaseAction)o).writeResonse();
				return ((BaseAction)o).getContentType();
			}
			return null;
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}
	}
	@SuppressWarnings("rawtypes")
	private String getParameter(Map parameterMap, String string) {
		try{
			return ((String[])parameterMap.get(string))[0];
		}catch(Exception e){
			return "";
		}
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void runAction(List<FileItem> items, ServletOutputStream out) throws Exception {
		try{
			// Process the uploaded items
			Iterator<FileItem> iter = items.iterator();
			String action = null;
			while (iter.hasNext()) {
			    FileItem item = iter.next();

			    if (item.isFormField()) {
			        continue;
			    } else {
			        String field = item.getFieldName();
			        if(field.equalsIgnoreCase("action")){
			        	action = item.getString();
			        	break;
			        }
			    }
			}
			if(action == null || action.trim().length() == 0){
				throw new Exception("No action specified");
			}
			AppDatabase.writeLog("00007: Running Action, "+action);
			Class[] parameterTypes = new Class[]{JSONObject.class};
			Class myClass = Class.forName(ACTION_PACKAGE+"."+action.split("[.]")[0]);
			Method meth = myClass.getMethod(action.split("[.]")[1], parameterTypes);
			Class[] constrpartypes = new Class[]{OutputStream.class,SessionData.class,HttpServletRequest.class};
			Constructor constr = myClass.getConstructor(constrpartypes);
			Object o = constr.newInstance(new Object[]{out,session,request});
			Object[] arglist = new Object[]{items};
			meth.invoke(o, arglist);
			if(o instanceof BaseAction){
				((BaseAction)o).writeResonse();
			}
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}
	}
	public HttpServletResponse getResponse() {
		return response;
	}
	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}
}
